# Copyright (c) 1998 Lawrence Livermore National Security, LLC and other
# HYPRE Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

function(find_hypre_dependency name)
  string(TOUPPER ${name} UPPER_NAME)
  if(HYPRE_ENABLE_${UPPER_NAME})
    find_dependency(${name} REQUIRED HINTS ${HYPRE_DEPENDENCY_DIRS})
    if(${name}_FOUND)
      message(STATUS "Found ${UPPER_NAME}: ${${name}_DIR}")
    else()
      message(FATAL_ERROR "${UPPER_NAME} not found.")
    endif()
  endif()
endfunction()

set(HYPRE_DEPENDENCY_DIRS "@HYPRE_DEPENDENCY_DIRS@")
set(HYPRE_ENABLE_BIGINT @HYPRE_ENABLE_BIGINT@)
set(HYPRE_ENABLE_MIXEDINT @HYPRE_ENABLE_MIXEDINT@)
set(HYPRE_ENABLE_SINGLE @HYPRE_ENABLE_SINGLE@)
set(HYPRE_ENABLE_LONG_DOUBLE @HYPRE_ENABLE_LONG_DOUBLE@)
set(HYPRE_ENABLE_COMPLEX @HYPRE_ENABLE_COMPLEX@)
set(HYPRE_ENABLE_MIXED_PRECISION @HYPRE_ENABLE_MIXED_PRECISION@)
set(HYPRE_ENABLE_HYPRE_BLAS @HYPRE_ENABLE_HYPRE_BLAS@)
set(HYPRE_ENABLE_HYPRE_LAPACK @HYPRE_ENABLE_HYPRE_LAPACK@)
set(HYPRE_ENABLE_PERSISTENT_COMM @HYPRE_ENABLE_PERSISTENT_COMM@)
set(HYPRE_ENABLE_FEI @HYPRE_ENABLE_FEI@)
set(HYPRE_ENABLE_MPI @HYPRE_ENABLE_MPI@)
set(HYPRE_ENABLE_OPENMP @HYPRE_ENABLE_OPENMP@)
set(HYPRE_ENABLE_HOPSCOTCH @HYPRE_ENABLE_HOPSCOTCH@)
set(HYPRE_ENABLE_PRINT_ERRORS @HYPRE_ENABLE_PRINT_ERRORS@)
set(HYPRE_ENABLE_TIMING @HYPRE_ENABLE_TIMING@)
set(HYPRE_ENABLE_HOST_MEMORY @HYPRE_ENABLE_HOST_MEMORY@)
set(HYPRE_ENABLE_TEST_USING_HOST @HYPRE_ENABLE_TEST_USING_HOST@)
set(HYPRE_ENABLE_CUDA @HYPRE_ENABLE_CUDA@)
set(HYPRE_ENABLE_HIP @HYPRE_ENABLE_HIP@)
set(HYPRE_ENABLE_SYCL @HYPRE_ENABLE_SYCL@)
set(HYPRE_ENABLE_UNIFIED_MEMORY @HYPRE_ENABLE_UNIFIED_MEMORY@)
set(HYPRE_ENABLE_CUDA_STREAMS @HYPRE_ENABLE_CUDA_STREAMS@)
set(HYPRE_ENABLE_DEVICE_MALLOC_ASYNC @HYPRE_ENABLE_DEVICE_MALLOC_ASYNC@)
set(HYPRE_ENABLE_THRUST_NOSYNC @HYPRE_ENABLE_THRUST_NOSYNC@)
set(HYPRE_ENABLE_CUSPARSE @HYPRE_ENABLE_CUSPARSE@)
set(HYPRE_ENABLE_CUBLAS @HYPRE_ENABLE_CUBLAS@)
set(HYPRE_ENABLE_CURAND @HYPRE_ENABLE_CURAND@)
set(HYPRE_ENABLE_CUSOLVER @HYPRE_ENABLE_CUSOLVER@)
set(HYPRE_ENABLE_GPU_AWARE_MPI @HYPRE_ENABLE_GPU_AWARE_MPI@)
set(HYPRE_ENABLE_GPU_PROFILING @HYPRE_ENABLE_GPU_PROFILING@)
set(HYPRE_ENABLE_ROCSPARSE @HYPRE_ENABLE_ROCSPARSE@)
set(HYPRE_ENABLE_ROCBLAS @HYPRE_ENABLE_ROCBLAS@)
set(HYPRE_ENABLE_ROCRAND @HYPRE_ENABLE_ROCRAND@)
set(HYPRE_ENABLE_ROCSOLVER @HYPRE_ENABLE_ROCSOLVER@)
set(HYPRE_ENABLE_ONEMKLSPARSE @HYPRE_ENABLE_ONEMKLSPARSE@)
set(HYPRE_ENABLE_ONEMKLBLAS @HYPRE_ENABLE_ONEMKLBLAS@)
set(HYPRE_ENABLE_ONEMKLRAND @HYPRE_ENABLE_ONEMKLRAND@)
set(HYPRE_BUILD_EXAMPLES @HYPRE_BUILD_EXAMPLES@)
set(HYPRE_BUILD_TESTS @HYPRE_BUILD_TESTS@)
set(HYPRE_ENABLE_DSUPERLU @HYPRE_ENABLE_DSUPERLU@)
set(HYPRE_ENABLE_MAGMA @HYPRE_ENABLE_MAGMA@)
set(HYPRE_ENABLE_CALIPER @HYPRE_ENABLE_CALIPER@)
set(HYPRE_ENABLE_UMPIRE @HYPRE_ENABLE_UMPIRE@)
set(HYPRE_ENABLE_UMPIRE_HOST @HYPRE_ENABLE_UMPIRE_HOST@)
set(HYPRE_ENABLE_UMPIRE_DEVICE @HYPRE_ENABLE_UMPIRE_DEVICE@)
set(HYPRE_ENABLE_UMPIRE_UM @HYPRE_ENABLE_UMPIRE_UM@)
set(HYPRE_ENABLE_UMPIRE_PINNED @HYPRE_ENABLE_UMPIRE_PINNED@)
set(HYPRE_HAVE_MPI_COMM_F2C @HYPRE_HAVE_MPI_COMM_F2C@)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")

if (UNIX)
  list(APPEND TPL_LIBRARIES m)
endif()

if(NOT HYPRE_ENABLE_HYPRE_BLAS)
  find_dependency(BLAS)
endif()

if(NOT HYPRE_ENABLE_HYPRE_LAPACK)
  find_dependency(LAPACK)
endif()

if(HYPRE_ENABLE_MPI)
  enable_language(C)
  find_dependency(MPI @MPI_C_VERSION@ COMPONENTS C)
endif()

if(HYPRE_ENABLE_OPENMP)
  find_dependency(OpenMP)
endif()

find_hypre_dependency(caliper)
find_hypre_dependency(dsuperlu)
find_hypre_dependency(magma)
find_hypre_dependency(umpire)

if(HYPRE_ENABLE_CUDA OR HYPRE_ENABLE_HIP OR HYPRE_ENABLE_SYCL)
  # List of required GPU libraries
  set(REQUIRED_GPU_COMPONENTS)

  if(HYPRE_ENABLE_CUDA)
    list(APPEND REQUIRED_GPU_COMPONENTS cudart)
    if(HYPRE_ENABLE_CUSPARSE)
      list(APPEND REQUIRED_GPU_COMPONENTS cusparse)
    endif()

    if(HYPRE_ENABLE_CUBLAS)
      list(APPEND REQUIRED_GPU_COMPONENTS cublas)
    endif()

    if(HYPRE_ENABLE_CURAND)
      list(APPEND REQUIRED_GPU_COMPONENTS curand)
    endif()

    if(HYPRE_ENABLE_CUSOLVER)
      list(APPEND REQUIRED_GPU_COMPONENTS cusolver)
    endif()
  elseif(HYPRE_ENABLE_HIP)
    if(HYPRE_ENABLE_ROCSPARSE)
      list(APPEND REQUIRED_GPU_COMPONENTS rocsparse)
    endif()

    if(HYPRE_ENABLE_ROCBLAS)
      list(APPEND REQUIRED_GPU_COMPONENTS rocblas)
    endif()

    if(HYPRE_ENABLE_ROCRAND)
      list(APPEND REQUIRED_GPU_COMPONENTS rocrand)
    endif()

    if(HYPRE_ENABLE_ROCSOLVER)
      list(APPEND REQUIRED_GPU_COMPONENTS rocsolver)
    endif()
  elseif(HYPRE_ENABLE_SYCL)
    if(HYPRE_ENABLE_ONEMKLSPARSE)
      list(APPEND REQUIRED_GPU_COMPONENTS onemklsparse)
    endif()

    if(HYPRE_ENABLE_ONEMKLBLAS)
      list(APPEND REQUIRED_GPU_COMPONENTS onemklblas)
    endif()

    if(HYPRE_ENABLE_ONEMKLRAND)
      list(APPEND REQUIRED_GPU_COMPONENTS onemklrand)
    endif()
  endif()

  if(REQUIRED_GPU_COMPONENTS)
    if(HYPRE_ENABLE_CUDA)
      set(GPU_TOOLKIT_NAME "CUDA")
      message(STATUS "Finding CUDA Toolkit components: ${REQUIRED_GPU_COMPONENTS}")
      find_dependency(CUDAToolkit REQUIRED COMPONENTS ${REQUIRED_GPU_COMPONENTS})
      set(GPU_TOOLKIT_FOUND ${CUDAToolkit_FOUND})
      set(GPU_TOOLKIT_VERSION ${CUDAToolkit_VERSION})

    elseif(HYPRE_ENABLE_HIP)
      # Add HIP root to prefix path to find ROCm components
      if(DEFINED ROCM_PATH)
        set(HIP_PATH ${ROCM_PATH})
      elseif(DEFINED ENV{ROCM_PATH})
        set(HIP_PATH $ENV{ROCM_PATH})
      elseif(DEFINED rocm_ROOT)
        set(HIP_PATH ${rocm_ROOT})
      elseif(DEFINED ENV{ROCM_ROOT})
        set(HIP_PATH $ENV{ROCM_ROOT})
      elseif(DEFINED hip_ROOT)
        set(HIP_PATH ${hip_ROOT})
      elseif(DEFINED ENV{hip_ROOT})
        set(HIP_PATH $ENV{hip_ROOT})
      elseif(EXISTS "/opt/rocm")
        set(HIP_PATH "/opt/rocm")
      else()
        message(WARNING "ROCM_PATH or HIP_PATH not set. Linking to ROCm libraries may not work.")
      endif()

      # Add HIP path to prefix path to find ROCm components
      list(APPEND CMAKE_PREFIX_PATH "${HIP_PATH}")

      set(GPU_TOOLKIT_NAME "HIP")
      message(STATUS "Finding HIP Toolkit components: ${REQUIRED_GPU_COMPONENTS}")
      find_dependency(hip REQUIRED)
      set(GPU_TOOLKIT_FOUND ${hip_FOUND})
      set(GPU_TOOLKIT_VERSION ${hip_VERSION})

      # Find ROCm components
      foreach(component ${REQUIRED_GPU_COMPONENTS})
        find_dependency(${component} REQUIRED)
      endforeach()

    elseif(HYPRE_ENABLE_SYCL)
      set(GPU_TOOLKIT_NAME "IntelSYCL")
      message(STATUS "Finding IntelSYCL Toolkit components: ${REQUIRED_GPU_COMPONENTS}")
      find_dependency(IntelSYCL REQUIRED)
      set(GPU_TOOLKIT_FOUND ${IntelSYCL_FOUND})
      set(GPU_TOOLKIT_VERSION ${IntelSYCL_VERSION})
    endif()

    if(GPU_TOOLKIT_FOUND)
      message(STATUS "GPU Toolkit found: ${GPU_TOOLKIT_NAME} ${GPU_TOOLKIT_VERSION}")
      set(MISSING_COMPONENTS)
      foreach(component ${REQUIRED_GPU_COMPONENTS})
        if(HYPRE_ENABLE_CUDA AND NOT TARGET CUDA::${component})
          list(APPEND MISSING_COMPONENTS ${component})
        elseif(HYPRE_ENABLE_HIP AND NOT TARGET roc::${component})
          list(APPEND MISSING_COMPONENTS ${component})
        elseif(HYPRE_ENABLE_SYCL AND NOT TARGET sycl::${component})
          list(APPEND MISSING_COMPONENTS ${component})
        endif()
      endforeach()
      if(MISSING_COMPONENTS)
        message(FATAL_ERROR "Required GPU components not found: ${MISSING_COMPONENTS}")
      else()
        message(STATUS "Required GPU components found: ${REQUIRED_GPU_COMPONENTS}")
      endif()
    else()
      message(FATAL_ERROR "GPU Toolkit not found.")
    endif()
  endif()
endif()

include("${CMAKE_CURRENT_LIST_DIR}/HYPRETargets.cmake")
